#include "Game.h"
#include "ScrTitle.h"
#include "ScrOverlay.h"
#include "Constant.h"
#ifdef WIN32
#include "ModLoader_win.h"
#else
#include "ModLoader_linux.h"
#endif

Game::Game() : m_fpsCounter(20)
{
	m_bRunning = true;
	m_nRetCode = 0;
	m_pScreenManager = NULL;
	m_pRenderer = NULL;
}
bool Game::InitRenderer()
{
	m_pRenderer = new Renderer();

	//Initialize renderer
	bool renderInit = m_pRenderer->Init(SCREEN_WIDTH, SCREEN_HEIGHT);

	return renderInit;
}
bool Game::Initialize()
{
	m_bRunning = true;
	m_nRetCode = 0;
	
	cout << "Init SDL" << endl;
	//Initialize SDL
	if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		Error(cout << "Failed to initialize SDL");
		return false;
	}

	cout << "Init Renderer" << endl;
	//Initialize Renderer
	if(!InitRenderer())
	{
		return false;
	}

	//Initialize screen manager
	m_pScreenManager = new ScreenManager();
	if(!m_pScreenManager->Init(this))
	{
		return false;
	}

	//Initialize ModLoader
#ifdef WIN32
	m_pModLoader = new ModLoader_win();
#else
	m_pModLoader = new ModLoader_linux();
#endif
	m_pModLoader->Initialize(PATH_MODS);

	GameScreenPtr titleScr = GameScreenPtr(new ScrTitle());
	m_pScreenManager->AddScreenAfter(titleScr);
	GameScreenPtr overlayScr = GameScreenPtr(new ScrOverlay());
	m_pScreenManager->AddScreenBefore(overlayScr);

	//Report end of initialization
	cout << "Done." << endl;
	LineSeperator();

	return true;
}
void Game::Cleanup()
{
	LineSeperator();
	CPrint(IBLUE | GREEN, cout << "Game Cleanup started" << endl);
	SetConsoleColor(IRED | GREEN);

	//Delete Screenmanager
	if(m_pScreenManager != NULL)
	{
		m_pScreenManager->Cleanup();
		Delete(m_pScreenManager);
	}

	if(m_pRenderer != NULL)
	{
		//Cleanup renderer
		m_pRenderer->Cleanup();
		Delete(m_pRenderer);
	}

	//Cleanup SDL
	SDL_Quit();
}
void Game::Quit(int c)
{
	m_bRunning = false;
	m_nRetCode = c;
}
int Game::GetTerminationCode()
{
	return m_nRetCode;
}
float Game::GetTimeDelta()
{
	return (float)m_frameTimer.GetTimeDelta();
}
int Game::Run()
{
	m_frameTimer.Start();

	//Call update and render functions
	SDL_Event e;
	while(SDL_PollEvent(&e))
	{
		HandleSDLEvent(e);
	}
	Update();
	Render();

	//Wait for frame time to end
	double fRunningTime = m_frameTimer.GetTimeRunning();

	/*
	if(fRunningTime < TIME_PER_FRAME)
	{
		double fWait = TIME_PER_FRAME - fRunningTime;
		SDL_Delay((Uint32)(fWait*1000));
	}
	*/
	//Now Using Verical Sync

	//Stop frame timer
	m_frameTimer.Stop();

	//Calculate frames per second
	m_fpsCounter.PushFrameTime(m_frameTimer.GetTimeDelta());

	return 0;
}
bool Game::IsGameRunning()
{
	return m_bRunning;
}
void Game::Render()
{
	m_pRenderer->Clear();
	m_pScreenManager->Render();
	m_pRenderer->Present();
}
void Game::HandleSDLEvent(SDL_Event e)
{
	if(e.type == SDL_QUIT)
	{
		Quit(5);
	}
	if(e.type == SDL_KEYDOWN)
	{
		uint d = SDL_GetModState();
		//LCTRL is The system commands modifier
		if((d == KMOD_LCTRL))
		{
			//Forced quit
			if(e.key.keysym.sym == SDLK_q)
			{
				Quit(0);
			}
			//Dump FPS to Console
			if((e.key.keysym.sym == SDLK_f))
			{
				cout << "FPS: " << m_fpsCounter.GetFPS() << endl;
			}
			//Dump screen Manager
			if(e.key.keysym.sym == SDLK_s)
			{
				m_pScreenManager->DumpScreensToSTD();
			}
		}

		//Handle game screen keys
		m_pScreenManager->OnKeyPress(e.key.keysym.sym);
	}
	if(e.type == SDL_KEYUP)
	{
		//Handle game screen keys
		m_pScreenManager->OnKeyRelease(e.key.keysym.sym);
	}
}
void Game::Update()
{
	m_pScreenManager->Update();
}
uint Game::GetFPS()
{
	return (uint)m_fpsCounter.GetFPS();
}
IScreenManager *Game::GetScreenManager()
{
	return m_pScreenManager;
}
IRenderer *Game::GetRenderer()
{
	return m_pRenderer;
}